package ru.spb.osll.myfit.client.widget;

import java.util.ArrayList;

import ru.spb.osll.myfit.client.PageMode;
import ru.spb.osll.myfit.client.event.PageEvent;
import ru.spb.osll.myfit.client.event.PageEvent.PageEventType;
import ru.spb.osll.myfit.common.PageElement;
import ru.spb.osll.myfit.common.PageElementType;

import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.MenuBar;
import com.google.gwt.user.client.ui.MenuItem;
import com.google.gwt.user.client.ui.PopupPanel;

public abstract class PageElementWidget extends Composite {

  protected PageMode m_mode;
  protected GWTWidgetFactory m_gwtWidgetFactory;
  protected PopupPanel m_rootPopupMenu;
  protected MenuBar m_rootMenuBar;
  protected ArrayList<PageEventListener> listeners = new ArrayList<PageEventListener>();

  public PageElementWidget(GWTWidgetFactory gwtWidgetFactory) {
    m_gwtWidgetFactory = gwtWidgetFactory;
    m_rootPopupMenu = m_gwtWidgetFactory.createPopupPanel();
    m_rootMenuBar = m_gwtWidgetFactory.createMenuBar();
    m_mode = PageMode.VIEW;
  }

  abstract public PageElement getPageElement();

  abstract public void setOpen(boolean isOpen);

  protected void createPopupMenu() {

    MenuItem deletePageElement = m_gwtWidgetFactory.createMenuItem("Delete",
        false, new Command() {

          @Override
          public void execute() {
            m_rootPopupMenu.hide();
            for (PageEventListener listener : listeners) {
              listener.actionPerformed(new PageEvent(
                  PageEventType.DELETE_PAGE_ELEMENT, false,
                  PageElementWidget.this));
            }
          }
        });

    MenuBar addElementBefore = m_gwtWidgetFactory.createMenuBar();

    MenuItem addIncludeBefore = m_gwtWidgetFactory.createMenuItem("Include", false,
                              createAddCommand(PageEventType.ADD_INCLUDE, true));
    MenuItem addTableBefore = m_gwtWidgetFactory.createMenuItem("Table", false,
                              createAddCommand(PageEventType.ADD_TABLE, true));
    MenuItem addWikiBefore = m_gwtWidgetFactory.createMenuItem("Wiki", false,
                              createAddCommand(PageEventType.ADD_WIKI, true));
    MenuItem addDefineBefore = m_gwtWidgetFactory.createMenuItem("Define", false,
                              createAddCommand(PageEventType.ADD_DEFINE, true));

    addElementBefore.addItem(addIncludeBefore);
    addElementBefore.addItem(addTableBefore);
    addElementBefore.addItem(addWikiBefore);
    addElementBefore.addItem(addDefineBefore);


    MenuBar addElementAfter = m_gwtWidgetFactory.createMenuBar();

    MenuItem addIncludeAfter = m_gwtWidgetFactory.createMenuItem("Include", false,
                              createAddCommand(PageEventType.ADD_INCLUDE, false));
    MenuItem addTableAfter = m_gwtWidgetFactory.createMenuItem("Table", false,
                              createAddCommand(PageEventType.ADD_TABLE, false));
    MenuItem addWikiAfter = m_gwtWidgetFactory.createMenuItem("Wiki", false,
                              createAddCommand(PageEventType.ADD_WIKI, false));
    MenuItem addDefineAfter = m_gwtWidgetFactory.createMenuItem("Define", false,
                              createAddCommand(PageEventType.ADD_DEFINE, false));

    addElementAfter.addItem(addIncludeAfter);
    addElementAfter.addItem(addTableAfter);
    addElementAfter.addItem(addWikiAfter);
    addElementAfter.addItem(addDefineAfter);


    m_rootMenuBar.addItem(deletePageElement);
    m_rootMenuBar.addItem("Add before...", addElementBefore);
    m_rootMenuBar.addItem("Add after...", addElementAfter);

    m_rootPopupMenu.setWidget(m_rootMenuBar);
  }

  private Command createAddCommand(final PageEventType type, final boolean isBefore) {
    return new Command() {
      @Override
      public void execute() {
        m_rootPopupMenu.hide();
        for (PageEventListener listener : listeners) {
          listener.actionPerformed(new PageEvent(type, isBefore,
                                          PageElementWidget.this));
        }
      }
    };
  }

  protected void emitPageEvent(PageEvent event) {
    for (PageEventListener listener : listeners)
      listener.actionPerformed(event);
  }

  public void setPageEventListener(PageEventListener pageEventListener) {
    listeners.add(pageEventListener);
  }

  public void removePageEventListener(PageEventListener pageEventListener) {
    listeners.remove(pageEventListener);
  }

  public abstract PageElementType getType();

  protected void onRightClick(Event event) {
    if (m_mode.equals(PageMode.VIEW)) {
      return;
    }
    int x = event.getClientX();
    int y = event.getClientY() + Window.getScrollTop();
    event.stopPropagation();
    m_rootPopupMenu.setPopupPosition(x, y);
    m_rootPopupMenu.show();
  }

  public void onBrowserEvent(Event event) {
    GWT.log("onBrowserEvent", null);
    event.preventDefault();
    switch (DOM.eventGetType(event)) {
    case Event.ONMOUSEUP:
      if (DOM.eventGetButton(event) == Event.BUTTON_LEFT) {
        GWT.log("Event.BUTTON_LEFT", null);
      }

      if (DOM.eventGetButton(event) == Event.BUTTON_RIGHT) {
        GWT.log("Event.BUTTON_RIGHT", null);
        onRightClick(event);
      }

      break;

    case Event.ONDBLCLICK:
      break;

    case Event.ONCONTEXTMENU:
      GWT.log("Event.ONCONTEXTMENU", null);
      break;

    default:
      break;
    }
  }

  public void setMode(PageMode mode) {
    m_mode = mode;
  }
}
